/**
 * 优化的背包数据访问层
 * 使用统一缓存系统，减少重复代码，提供批量查询功能
 */

import { ModernBaseService } from '../service/base/ModernBaseService';
import { RepositoryHelper } from '../infrastructure/repository/RepositoryHelper';
import { Item } from '../shared/face';

/**
 * 背包数据接口
 */
interface PlayerBagData {
    playerId: string;
    items: Item[];
    maxSize: number;
    lastUpdated: Date;
}

/**
 * 优化的背包Repository
 * 使用统一的缓存和批量查询
 */
export class OptimizedBagRepository extends ModernBaseService {
    private readonly CACHE_TTL = 300000; // 5分钟缓存
    private readonly CACHE_PREFIX = 'bag';

    /**
     * 获取玩家背包数据
     * 使用统一缓存系统
     */
    async getPlayerBag(playerId: string): Promise<PlayerBagData> {
        RepositoryHelper.validateRequiredParams({ playerId }, ['playerId']);
        
        const cacheKey = RepositoryHelper.buildCacheKey(this.CACHE_PREFIX, playerId);
        
        return RepositoryHelper.withCache(
            cacheKey,
            () => this.loadBagFromSource(playerId),
            this.CACHE_TTL
        );
    }

    /**
     * 批量获取多个玩家的背包数据
     * 优化查询，避免N+1问题
     */
    async getPlayerBags(playerIds: string[]): Promise<Map<string, PlayerBagData>> {
        if (playerIds.length === 0) {
            return new Map();
        }
        
        return RepositoryHelper.batchGet(
            playerIds,
            this.CACHE_PREFIX,
            (uncachedIds) => this.batchLoadBags(uncachedIds),
            this.CACHE_TTL
        );
    }

    /**
     * 获取多个玩家背包数据（保持顺序）
     */
    async getPlayerBagsOrdered(playerIds: string[]): Promise<(PlayerBagData | null)[]> {
        if (playerIds.length === 0) {
            return [];
        }
        
        return RepositoryHelper.batchGetOrdered(
            playerIds,
            this.CACHE_PREFIX,
            (uncachedIds) => this.batchLoadBags(uncachedIds),
            this.CACHE_TTL
        );
    }

    /**
     * 更新玩家背包数据
     * 更新后刷新缓存
     */
    async updatePlayerBag(playerId: string, updateData: Partial<PlayerBagData>): Promise<PlayerBagData> {
        RepositoryHelper.validateRequiredParams({ playerId }, ['playerId']);
        
        // 先获取当前数据
        const currentData = await this.getPlayerBag(playerId);
        
        // 合并更新数据
        const updatedData = {
            ...currentData,
            ...updateData,
            lastUpdated: new Date()
        };
        
        // 保存到数据源（这里简化处理）
        await this.saveBagToSource(playerId, updatedData);
        
        // 刷新缓存
        const cacheKey = RepositoryHelper.buildCacheKey(this.CACHE_PREFIX, playerId);
        return RepositoryHelper.refreshCache(
            cacheKey,
            () => Promise.resolve(updatedData),
            this.CACHE_TTL
        );
    }

    /**
     * 添加物品到背包
     * 优化的单项操作
     */
    async addItemToBag(playerId: string, item: Item): Promise<PlayerBagData> {
        const bagData = await this.getPlayerBag(playerId);
        
        // 检查背包空间
        if (bagData.items.length >= bagData.maxSize) {
            throw new Error('Bag is full');
        }
        
        // 检查是否可以堆叠
        const existingItem = bagData.items.find(existing => 
            existing.itemId === item.itemId && this.canStack(existing, item)
        );
        
        if (existingItem) {
            // 堆叠物品
            existingItem.count = (existingItem.count || 1) + (item.count || 1);
        } else {
            // 添加新物品
            bagData.items.push(item);
        }
        
        return this.updatePlayerBag(playerId, { items: bagData.items });
    }

    /**
     * 从背包移除物品
     */
    async removeItemFromBag(playerId: string, itemId: string, count: number = 1): Promise<PlayerBagData> {
        const bagData = await this.getPlayerBag(playerId);
        
        const itemIndex = bagData.items.findIndex(item => item.itemId === itemId);
        if (itemIndex === -1) {
            throw new Error(`Item ${itemId} not found in bag`);
        }
        
        const item = bagData.items[itemIndex];
        const currentCount = item.count || 1;
        
        if (currentCount <= count) {
            // 移除整个物品
            bagData.items.splice(itemIndex, 1);
        } else {
            // 减少数量
            item.count = currentCount - count;
        }
        
        return this.updatePlayerBag(playerId, { items: bagData.items });
    }

    /**
     * 清空背包缓存
     */
    clearBagCache(playerId?: string): number {
        if (playerId) {
            const cacheKey = RepositoryHelper.buildCacheKey(this.CACHE_PREFIX, playerId);
            return RepositoryHelper.invalidateCache(cacheKey) ? 1 : 0;
        } else {
            return RepositoryHelper.invalidateCacheByPrefix(`${this.CACHE_PREFIX}:`);
        }
    }

    /**
     * 预热背包缓存
     * 为活跃玩家预先加载数据
     */
    async warmupBagCache(playerIds: string[]): Promise<void> {
        const warmupPromises = playerIds.map(async playerId => {
            const cacheKey = RepositoryHelper.buildCacheKey(this.CACHE_PREFIX, playerId);
            await RepositoryHelper.warmupCache(
                cacheKey,
                () => this.loadBagFromSource(playerId),
                this.CACHE_TTL
            );
        });
        
        await Promise.allSettled(warmupPromises);
    }

    /**
     * 获取背包统计信息
     */
    async getBagStats(playerId: string): Promise<{
        totalItems: number;
        usedSlots: number;
        freeSlots: number;
        totalValue: number;
    }> {
        const cacheKey = RepositoryHelper.buildCacheKey('bag_stats', playerId);
        
        return RepositoryHelper.withCache(
            cacheKey,
            async () => {
                const bagData = await this.getPlayerBag(playerId);
                const totalItems = bagData.items.reduce((sum, item) => sum + (item.count || 1), 0);
                const usedSlots = bagData.items.length;
                const freeSlots = bagData.maxSize - usedSlots;
                
                // 计算总价值（简化处理）
                const totalValue = bagData.items.reduce((sum, item) => {
                    const itemValue = this.getItemValue(item);
                    return sum + itemValue * (item.count || 1);
                }, 0);
                
                return {
                    totalItems,
                    usedSlots,
                    freeSlots,
                    totalValue
                };
            },
            60000 // 统计数据缓存1分钟
        );
    }

    // ==================== 私有方法 ====================

    /**
     * 从数据源加载背包数据
     */
    private async loadBagFromSource(playerId: string): Promise<PlayerBagData> {
        const player = this.sdk.getPlayerById(playerId);
        if (!player) {
            throw new Error(`Player ${playerId} not found`);
        }

        const bagComponent = player.getComponent('背包');
        if (!bagComponent) {
            return this.createDefaultBag(playerId);
        }

        return {
            playerId,
            items: this.convertItemsToEntities(bagComponent.itemList || []),
            maxSize: bagComponent.maxSize || 100,
            lastUpdated: new Date()
        };
    }

    /**
     * 批量加载背包数据
     */
    private async batchLoadBags(playerIds: string[]): Promise<Map<string, PlayerBagData>> {
        const result = new Map<string, PlayerBagData>();
        
        // 并行加载所有玩家的背包数据
        const loadPromises = playerIds.map(async playerId => {
            try {
                const bagData = await this.loadBagFromSource(playerId);
                result.set(playerId, bagData);
            } catch (error) {
                console.warn(`Failed to load bag for player ${playerId}:`, error);
                // 加载失败时，创建默认背包
                try {
                    const defaultBag = this.createDefaultBag(playerId);
                    result.set(playerId, defaultBag);
                } catch (defaultError) {
                    console.error(`Failed to create default bag for player ${playerId}:`, defaultError);
                }
            }
        });
        
        await Promise.allSettled(loadPromises);
        return result;
    }

    /**
     * 保存背包数据到数据源
     */
    private async saveBagToSource(playerId: string, bagData: PlayerBagData): Promise<void> {
        const player = this.sdk.getPlayerById(playerId);
        if (!player) {
            throw new Error(`Player ${playerId} not found`);
        }

        const bagComponent = player.getComponent('背包');
        if (bagComponent) {
            bagComponent.itemList = this.convertEntitiesToItems(bagData.items);
            bagComponent.maxSize = bagData.maxSize;
        }
    }

    /**
     * 创建默认背包
     */
    private createDefaultBag(playerId: string): PlayerBagData {
        return {
            playerId,
            items: [],
            maxSize: 100,
            lastUpdated: new Date()
        };
    }

    /**
     * 转换物品格式
     */
    private convertItemsToEntities(items: any[]): Item[] {
        return items.map(item => ({
            itemId: item.itemId || item.id,
            count: item.count || 1,
            name: item.name || '',
            description: item.description || '',
            ...item
        }));
    }

    /**
     * 转换实体格式回物品格式
     */
    private convertEntitiesToItems(items: Item[]): any[] {
        return items.map(item => ({
            itemId: item.itemId,
            count: item.count,
            name: item.name,
            description: item.description
        }));
    }

    /**
     * 检查物品是否可以堆叠
     */
    private canStack(item1: Item, item2: Item): boolean {
        return item1.itemId === item2.itemId && 
               !item1.uniqueId && !item2.uniqueId; // 唯一物品不能堆叠
    }

    /**
     * 获取物品价值
     */
    private getItemValue(item: Item): number {
        // 这里应该从配置中获取，暂时返回固定值
        return 10;
    }
}
